import chartFactory from '../index';

const chart = {};

chart.create = chartFactory

chart.init = function (opt) {
  this.create(opt);
  this.tooltip = d3.select(this.config.target + ` .tooltip`);
}

chart.update = function (_data, template) {
  this.data = this.data || _data;
  this.template = this.template || template;

  if (this.template == null || this.data == null)
    return; // 初始状态下可能并无数据，或为了扩展空间

  let parent = document.querySelector(this.config.target);

  this.width = parent.clientWidth - this.config.margin.left - this.config.margin.right;
  this.height = parent.clientHeight - this.config.margin.top - this.config.margin.bottom;



  let dataSample = this.process(this.data, this.template);

  this.y = d3.scaleBand().domain(d3.range(0, dataSample.result.length))
    .rangeRound([this.height, 0]).paddingInner(0.3)

  this.x = d3.scaleBand().domain(dataSample.nodes)
    .rangeRound([0, this.width]).paddingInner(0.1)

  // cover-bar映射
  // this.x_cover = d3.scaleLinear()
  //   .domain([0, d3.max(dataSample.map(d => {
  //     return d[0].cover_num;
  //   }))])
  //   .range([0, this.x(0)]);

  let self = this;

  let updateGroups = this.container.selectAll('.composition').data(dataSample.result),
    enterGroups = updateGroups.enter(), exitGroups = updateGroups.exit();
  exitGroups.remove();

  enterGroups.append('g').classed('composition', true).merge(updateGroups)
    .on('click', function (d) {


      // if (d3.select(d3.event.target).data[0]['used'] === false)
      //return;  该定向没有被使用到，因此不应产生下钻行为
      // 暂存该条定向组合使用到的定向

      // 查找对应定向的子定向,当点击某一个Rect时，可以使用以下方式查找子定向
      let clickedTarget = d3.select(d3.event.target).data()[0]
      let children = self.template.map(item => item.parent === clickedTarget.name ? item.name : undefined)
        .filter(val => val)
      if (children.length === 0)
        return // 被点击的定向已经是最低一级定向，也不应产生下钻行为

      let used = d.usedTargetsInLevel[clickedTarget.level + 1]

      // children 代表的是点击了某一个Rect之后，该定向所对应的子级定向
      // 为该定向组合单独设置X轴比例尺
      self.x.domain(children)

      // 对数据进行处理
      let model = children.map(item => Object.assign({}, { name: item, used: false, level: clickedTarget.level + 1 }))
      used.forEach(target => {
        let index = model.findIndex(item => item.name === target.name);
        if (index !== -1) {
          // 证明使用了该定向
          model[index].used = true
        }
      })

      // 至此已经为该条定向组合的下钻行为找到了数据
      // 为了保证下钻行为能够返回上一步的状态，应将上一步的数据保存下来

      // d3.select(this).append('g').attr('class', 'axis x-axis')
      //   .attr('transform', 'translate(0, 15)')
      //   .call(d3.axisBottom().scale(self.x))


      let updateRects = d3.select(this).selectAll('rect').data(model),
        enterRects = updateRects.enter(), exitRects = updateRects.exit();
      exitRects.remove();

      enterRects.append('rect').merge(updateRects)
        .attr('x', (d, i) => self.x(d.name))
        .attr('height', self.y.bandwidth())
        .attr('width', self.x.bandwidth())
        .attr('stroke', '#000')
        .attr('stroke-width', 0.3)
        .attr('class', d => {
          if (d.used === true) {
            return `level-${d.level} active`
          } else {
            return ''
          }
        })
    })

  let updateBars = d3.selectAll('.composition')
    .attr('transform', (d, i) => `translate(0, ${this.y(i)})`)
    .selectAll('rect').data(d => d),
    enterBars = updateBars.enter(), exitBars = updateBars.exit();
  exitBars.remove();

  enterBars.append('rect').merge(updateBars)
    .attr('height', this.y.bandwidth())
    .attr('width', this.x.bandwidth())
    .attr('x', (d, i) => this.x(d.name))
    .attr('class', d => {
      if (d.used === true) {
        return `level-${d.level} active`
      } else {
        return ''
      }
    })
    .on('mouseenter', d =>
      this.tooltip.style('visibility', 'visible')
    ).on('mouseleave', d => this.tooltip.style('visibility', 'hidden'))
    .on('mousemove', d => {
      let tooltipStr = `定向名称: ${d.name}`;
      this.tooltip.html(tooltipStr);
      this.tooltip.style('left', d3.event.pageX + 10 + 'px');
      this.tooltip.style('top', d3.event.pageY + 10 + 'px')
    })

  // 人群覆盖量矩形
  // let coverBars = this.container.selectAll('.composition').data(dataSample)
  //   .append('rect').attr('height', this.y.bandwidth())
  //   .attr('width', (d, i) => {
  //     return this.x_cover(d[0].cover_num)
  //   })
  //   .attr('x', this.x(0))
  //   .attr('fill', '#253494');

}

chart.process = function (data, template) {

  let result = []; // 用于保存定向组合结果
  let firstTargets = template.map(item => item.level === 1 ? item.name : null).filter(val => val)

  // 目前先按照频次排名前20来展示定向组合
  let topDataset = data.slice(0, 20)
  topDataset.forEach(item => {
    // 获取该条定向组合使用到的各个定向
    let currentTargets = item.usedtargets.split(',')
    let targets = template.map(target => currentTargets.indexOf(target.name) !== -1 ? target : undefined).filter(val => val)

    let usedTargetsInLevel = {}
    for (let i = 0; i < 3; ++i) {
      usedTargetsInLevel[i] = []
    }
    // 为保证下钻功能，应当依据targets层层向上遍历
    targets.forEach(t => {
      if (t !== null) {
        usedTargetsInLevel[t.level].push(t)
      }
      // 开始向上遍历
      while (t.parent != "根定向") {
        // 寻找t的parent节点
        let parent = template.filter(target => target.name === t.parent)[0]
        if (parent != null) {
          // 找到了父节点
          // 避免重复插入
          if (usedTargetsInLevel[parent.level].findIndex(item => item.name === parent.name) === -1) {
            usedTargetsInLevel[parent.level].push(parent)
          }

        }
        t = parent;
      }

    })
    // 此时tempResult代表一条定向组合
    // 初始状态下先展示一级定向的使用情况

    let allTargetInLevelOne = template.map(target => target.level === 1 ? Object.assign({}, { used: false, name: target.name, level: 1 }) : undefined).filter(val => val)
    // 此时构造了7个节点，默认均没有被使用
    usedTargetsInLevel['1'].forEach(target => {
      let index = allTargetInLevelOne.findIndex(item => item.name === target.name)
      if (index !== -1) {
        allTargetInLevelOne[index].used = true
      }
    })

    allTargetInLevelOne.usedTargetsInLevel = usedTargetsInLevel
    allTargetInLevelOne.actions = []
    result.push(allTargetInLevelOne)
  })

  return { result, nodes: firstTargets }

}



export default chart;